package labox.innovation.gameserver.datatables;

import java.io.File;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import javolution.util.FastMap;
import labox.innovation.config.Config;
import labox.innovation.db.core.L2DatabaseFactory;
import labox.innovation.gameserver.model.L2AccessLevel;
import labox.innovation.gameserver.model.L2AdminCommandAccessRight;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;


/**
 * @author FBIagent<br>
 */
public class AdminCommandAccessRights {
	/** The logger<br> */
	private static Logger _log = LoggerFactory.getLogger(AdminCommandAccessRights.class.getName());

	private Map<String, L2AdminCommandAccessRight> _adminCommandAccessRights;
	
	private Map<String, String> _adminCommandAccessRight;

	/**
	 * Returns the one and only instance of this class<br><br>
	 * 
	 * @return AdminCommandAccessRights: the one and only instance of this class<br>
	 */
	public static AdminCommandAccessRights getInstance() {
		return SingletonHolder._instance;
	}

	/** The access rights<br> */
	private AdminCommandAccessRights() {
//		loadAdminCommandAccessRights();
		loadAdminCommandAccessConfig();
	}

	/**
	 * Loads admin command access rights from database<br>
	 */
	private void loadAdminCommandAccessRights() {
		_adminCommandAccessRights = new FastMap<String, L2AdminCommandAccessRight>();

		Connection con = null;

		try {
			con = L2DatabaseFactory.getInstance().getConnection();

			PreparedStatement stmt = con.prepareStatement("SELECT * FROM admin_command_access_rights");
			ResultSet rset = stmt.executeQuery();
			String adminCommand = null;
			String accessLevels = null;

			while (rset.next()) {
				adminCommand = rset.getString("adminCommand");
				accessLevels = rset.getString("accessLevels");
				_adminCommandAccessRights.put(adminCommand, new L2AdminCommandAccessRight(adminCommand, accessLevels));
			}
			rset.close();
			stmt.close();
		} catch (SQLException e) {
			_log.error("AdminCommandAccessRights: Error loading from database:", Config.SERVER_ID,e);
		} finally {
			try {
				con.close();
			} catch (Exception e) {
			}
		}

		_log.info("AdminCommandAccessRights: Loaded " + _adminCommandAccessRights.size() + " from database.");
	}

	/**
	 * 载入配置信息到内存
	 */
	private void loadAdminCommandAccessConfig()
	{
		_adminCommandAccessRight = new FastMap<String, String>();
		FileInputStream fs = null;
		try {
			File file = new File(Config.DATAPACK_ROOT, "/data/xml/access/accessLevel.xml");
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			fs = new FileInputStream(file);
			Document document = builder.parse(fs);
			Element root;
			root = document.getDocumentElement();
			
			if (root.getTagName().compareTo("AccessLevel") != 0) {
				throw new Exception("Not a accessLevel file!");
			}

			Element parentNode = null;
			NodeList list = root.getElementsByTagName("popedom");
			String adminCommand = null;
			String accessLevels = null;
			for (int i = 0; i < list.getLength(); i++) {
				parentNode = (Element)list.item(i);
				adminCommand = parentNode.getAttribute("cmd");
				accessLevels = parentNode.getAttribute("accessLevels");

				if (adminCommand == null  || accessLevels.trim().length() == 0) 
					continue;
				
				_adminCommandAccessRight.put(adminCommand, accessLevels);
			}
		
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		_log.info("AdminCommandAccessRight: Loaded " + _adminCommandAccessRight.size() + " from accessLevel.xml.");
	}

	public boolean hasAccess(String adminCommand, L2AccessLevel accessLevel) {
		if (!accessLevel.isGm())
			return false;
		
		if (accessLevel.getLevel() == AccessLevels._masterAccessLevelNum)
			return true;

		String userLevels = _adminCommandAccessRight.get(adminCommand);
		String level = String.valueOf(accessLevel.getLevel());
		if (userLevels == null || !userLevels.contains(level)) {
			_log.info("AdminCommandAccessRights: No rights defined for admin command " + adminCommand + ".");
			return false;
		}

		return true;
	}

	public void reloadAdminCommandAccessRights() {
		loadAdminCommandAccessRights();
	}

	@SuppressWarnings("synthetic-access")
	private static class SingletonHolder {
		protected static final AdminCommandAccessRights _instance = new AdminCommandAccessRights();
	}
}